import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;

import org.w3c.dom.*;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

public class ProductList
{
	private ArrayList<Product> allProducts;
	File file;
	static final Boolean AUTO_SAVE = true;

	// Constructor
	ProductList(String xmlFileName)
	{
		this.allProducts = new ArrayList<Product>();	// Create new "Product List"
		this.file = new File(xmlFileName);				// Create new "file handler"
		this.load();									// Check if file exists and load products
		Collections.sort(allProducts);					// Sort products in List
	}
	
	// Add product to list.
	private void add(Product p)
	{
		if (p != null)
		{
			allProducts.add(p);
		}
	}

	// Add new product to list, sort and auto-save.
	void Add(Product p)
	{
		this.add(p);
		Collections.sort(allProducts);
		this.autosave();
	}
	
	void Remove(Product p)
	{
		if ((p != null) && (allProducts.contains(p)))
		{
			allProducts.remove(p);
			System.out.println("Removed product: " + p.toString());
			this.autosave();
		}
		else
		{
			System.out.println("Failed to remove product: " + p.toString());
		}
	}

	void list()
	{
		for (Product p : allProducts)
		{
			System.out.println(p.toString());
		}
	}

	void load()
	{
		if (file.exists())
		{
			this.loadFromXml();
		}
	}

	void save()
	{
		// Check if file exists
		if (!file.exists())
		{
			try
			{
				file.createNewFile();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		this.saveToXml();
	}

	Product getProductByName(String name)
	{
		name = name.trim();
		for (Product p : allProducts)
		{
			if (p.getName().equals(name))
			{
				return p;
			}
		}
		System.out.println("Product " + name + " not found!");
		return null;
	}

	private void loadFromXml()
	{
		try
		{
			Document document;
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			document = db.parse(file);
			document.getDocumentElement().normalize();

			NodeList node = document.getElementsByTagName("Product");
			// System.out.println("Products in XML Database(" + node.getLength() + "): ");

			for (int i = 0; i < node.getLength(); i++)
			{
				Node firstNode = node.item(i);

				if (firstNode.getNodeType() == Node.ELEMENT_NODE)
				{
					Element element = (Element)firstNode;
					
					// Read name from XML
					String name = element.getElementsByTagName("name").item(0).getTextContent();
					
					// Read unit from XML
					String unit = element.getElementsByTagName("unit").item(0).getTextContent();
					
					// Read quantity from XML
					String quantityString = element.getElementsByTagName("quantity").item(0).getTextContent();
					int quantity = Integer.parseInt(quantityString);
					
					// Read shop from XML
					String shop =  element.getElementsByTagName("shop").item(0).getTextContent();
					
					String dateString = element.getElementsByTagName("date").item(0).getTextContent();
					Date date = DateFormat.getDateTimeInstance().parse(dateString);

					// Add product with XML data.
					Product p = new Product(name, quantity, unit, shop, date);
					this.add(p);
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	private void saveToXml()
	{
		try
		{
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder parser = factory.newDocumentBuilder();
			Document document = parser.newDocument();

			Element root = document.createElement("Products");

			for (Product p : allProducts)
			{
				Node newProduct = document.createElement("Product");

				Node newName = document.createElement("name");
				Node nameValue = document.createTextNode(p.getName());
				newName.appendChild(nameValue);

				Node newQuantity = document.createElement("quantity");
				Node quantityValue = document.createTextNode(p.getQuantity().toString());
				newQuantity.appendChild(quantityValue);

				Node newUnit = document.createElement("unit");
				Node unitValue = document.createTextNode(p.getUnit());
				newUnit.appendChild(unitValue);
				
				Node newShop = document.createElement("shop");
				Node shopValue = document.createTextNode(p.getShop());
				newShop.appendChild(shopValue);
				
				Node newDate = document.createElement("date");
				Date date = p.getDate();
				Node dateValue = document.createTextNode(DateFormat.getDateTimeInstance().format(date));
				newDate.appendChild(dateValue);
				
				newProduct.appendChild(newName);
				newProduct.appendChild(newQuantity);
				newProduct.appendChild(newUnit);
				newProduct.appendChild(newShop);
				newProduct.appendChild(newDate);

				root.appendChild(newProduct);
			}
			document.appendChild(root);

			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();

			DOMSource source = new DOMSource(document);

			StreamResult result = new StreamResult(file);
			transformer.transform(source, result);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	private void autosave()
	{
		if (AUTO_SAVE)
		{
			this.save();
		}
	}
}
